package circular_buffer;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConcurrencyCircularBuffer<T> extends AbstractCircularBuffer<T> {

	private final Lock lock = new ReentrantLock(); 
    
    private final Condition isEmptyBuffer = lock.newCondition();
    private final Condition isFullBuffer = lock.newCondition();
	
	public ConcurrencyCircularBuffer(int maxSize) {
		this.maxSize = maxSize;
	}
	
	@Override
	public void put(T elem) {
		 lock.lock();
	        try {
	            while(isFull()){
	                try {
	                    isFullBuffer.await();
	                } catch (InterruptedException e) {
	                    e.printStackTrace();
	                }
	                
	            }
	            buffer.addLast(elem);
	            isEmptyBuffer.signal();
	        } finally {
	            lock.unlock();
	        }
	}

	@Override
	public T get() {
		lock.lock();
        try {
            while (buffer.isEmpty()){
                try {
                    isEmptyBuffer.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
         }   
         T result = buffer.removeFirst();
         isFullBuffer.signal();
         return result;
        } finally {
            lock.unlock();
        }
	}

}
